<template>
  <el-dialog
    title="九宫格预览"
    :visible.sync="dialogVisible"
    width="800px"
    class="grid-dialog"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <!-- 九宫格图片区域 -->
    <div class="grid-container">
      <div
        v-for="(item, index) in displayData"
        :key="index"
        class="image-item"
        :class="{ 'empty-item': !item.playerId }"
        draggable="true"
        @dragstart="handleDragStart($event, index)"
        @dragover="handleDragOver"
        @drop="handleDrop($event, index)"
      >
        <div v-if="item.playerId" class="image-wrapper">
          <el-image :src="item.imageUrl" fit="cover">
            <div slot="error" class="image-slot">
              <i class="el-icon-picture-outline"></i>
            </div>
          </el-image>
          <div class="replace-btn" @click="handleReplace(item)">
            <i class="el-icon-refresh-right"></i>
            替换
          </div>
        </div>
        <div v-else class="image-slot">
          <i class="el-icon-picture-outline"></i>
        </div>
      </div>
    </div>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
        :current-page.sync="currentPage"
        :page-size="pageSize"
        :total="total"
        layout="prev, pager, next"
        @current-change="handlePageChange"
      />
    </div>

    <div slot="footer" class="dialog-footer">
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" @click="handleConfirm">确认</el-button>
    </div>

    <!-- 替换图片弹窗 -->
    <el-dialog
      title="替换图片"
      :visible.sync="replaceDialogVisible"
      width="400px"
      append-to-body
    >
      <el-form>
        <el-form-item label="上传图片">
          <el-upload
            class="upload-demo"
            action=""
            :http-request="handleUpload"
            :show-file-list="false"
            accept="image/*"
          >
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div>
          </el-upload>
        </el-form-item>
        <el-form-item v-if="previewUrl">
          <img
            :src="previewUrl"
            style="width: 100%; max-height: 200px; object-fit: contain"
          />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="handleCancelReplace">取消</el-button>
        <el-button
          type="primary"
          @click="confirmReplace"
          :disabled="!uploadedFile"
          >确认</el-button
        >
      </div>
    </el-dialog>
  </el-dialog>
</template>

<script>
import { getFile, put, getFileNameUUID, getFileName } from "@/utils/ali-oss";
import { listVote, editVote } from "@/api/vote";

export default {
  name: "GridPreview",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      currentPage: 1,
      pageSize: 9,
      total: 0,
      gridData: [],
      imageUrls: [],
      replaceDialogVisible: false,
      currentReplaceItem: null,
      uploadedFile: null,
      previewUrl: "",
      dialogVisible: false,
    };
  },
  computed: {
    totalPages() {
      return Math.ceil(this.total / this.pageSize);
    },
    displayData() {
      return this.gridData.map((item) => ({
        id: item.id,
        playerId: item.playerId,
        playerName: item.playerName,
        imageUrl: item.imageUrl || "",
        vateImages: item.vateImages,
        sort: item.sort,
      }));
    },
  },
  watch: {
    visible: {
      immediate: true,
      handler(val) {
        this.dialogVisible = val;
        if (val) {
          this.currentPage = 1;
          this.init();
        }
      },
    },
  },
  methods: {
    handleDragStart(event, index) {
      event.dataTransfer.setData("text/plain", index);
    },
    handleDragOver(event) {
      event.preventDefault();
    },
    handleDrop(event, index) {
      event.preventDefault();
      const dragIndex = event.dataTransfer.getData("text/plain");
      this.swapImages(parseInt(dragIndex), index);
    },
    swapImages(fromIndex, toIndex) {
      this.$emit("swap", fromIndex, toIndex);
    },
    handleReplace(item) {
      this.currentReplaceItem = item;
      this.uploadedFile = null;
      this.previewUrl = "";
      this.replaceDialogVisible = true;
    },
    async handleUpload(params) {
      try {
        // 这里可以添加文件大小和类型的验证
        const file = params.file;
        if (!file.type.includes("image/")) {
          this.$message.error("请上传图片文件");
          return;
        }

        this.uploadedFile = file;
        // 创建本地预览
        this.previewUrl = URL.createObjectURL(file);
      } catch (error) {
        console.error("上传失败:", error);
        this.$message.error("上传失败");
      }
    },
    handleCancelReplace() {
      this.replaceDialogVisible = false;
      this.uploadedFile = null;
      this.previewUrl = "";
    },
    async confirmReplace() {
      if (!this.uploadedFile) {
        this.$message.warning("请先上传图片");
        return;
      }

      // 检查文件类型
      if (!this.uploadedFile.type.includes("image/")) {
        this.$message.error("只能上传图片文件");
        return;
      }

      try {
        this.$loading({
          lock: true,
          text: "上传中...",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.7)",
        });

        // 1. 生成唯一文件名并上传到阿里云OSS
        const fileName =
          getFileNameUUID() + getFileName(this.uploadedFile.name);
        const ossResult = await put(fileName, this.uploadedFile);

        if (!ossResult) {
          throw new Error("上传到OSS失败");
        }

        // 2. 调用后端接口更新数据
        const params = {
          id: this.currentReplaceItem.id,
          playerId: this.currentReplaceItem.playerId,
          playerName: this.currentReplaceItem.playerName,
          vateImages: fileName, // 使用OSS返回的文件名
        };

        await editVote(params);

        // 3. 成功处理
        this.$message.success("替换成功");
        this.replaceDialogVisible = false;
        this.uploadedFile = null;
        this.previewUrl = "";

        // 4. 刷新数据
        await this.fetchGridData();

        // 5. 通知父组件更新
        this.$emit("success");
      } catch (error) {
        console.error("替换失败:", error);
        this.$message.error(error.message || "替换失败");
      } finally {
        this.$loading().close();
      }
    },
    handleConfirm() {
      this.$emit("confirm");
      this.$emit("update:visible", false);
    },
    async updateImageUrls(list) {
      // 只处理实际存在的数据
      const urls = await Promise.all(
        list.map(async (item) => {
          if (item?.vateImages) {
            const url = await getFile(item.vateImages);
            // 直接更新item的imageUrl
            item.imageUrl = url;
            return url;
          }
          return "";
        })
      );
      this.imageUrls = urls;
    },
    async fetchGridData() {
      try {
        const params = {
          pageNum: this.currentPage,
          pageSize: this.pageSize,
        };
        const response = await listVote(params);
        // 处理每一行数据，获取图片真实地址
        this.gridData = await Promise.all(
          response.rows.map(async (item) => ({
            ...item,
            imageUrl: await getFile(item.vateImages),
          }))
        );
        this.total = response.total;
      } catch (error) {
        console.error("获取九宫格数据失败:", error);
        this.$message.error("获取数据失败");
      }
    },
    async handlePageChange(page) {
      this.currentPage = page;
      await this.fetchGridData();
    },
    async init() {
      if (this.dialogVisible) {
        await this.fetchGridData();
      }
    },
    handleClose() {
      this.$emit("update:visible", false);
    },
  },
};
</script>

<style scoped>
.grid-dialog {
  .el-dialog__body {
    padding: 20px;
    min-height: 800px; /* 设置最小高度，确保三行显示 */
  }
}

.grid-container {
  overflow: hidden;
  padding: 10px;
  min-height: 750px; /* 设置最小高度，确保三行显示 */
}

.image-item {
  float: left;
  width: calc(33.33% - 10px);
  margin: 5px;
  position: relative;
  border: 1px dashed #ccc;
  aspect-ratio: 1;
  cursor: move;
  height: 250px;
}

.empty-item {
  background-color: #f5f7fa;
  cursor: default;
}

.image-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.el-image {
  width: 100%;
  height: 100%;
}

.replace-btn {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(64, 158, 255, 0.8);
  color: #fff;
  padding: 8px 15px;
  border-radius: 4px;
  cursor: pointer;
  display: none;
  align-items: center;
  gap: 5px;
}

.image-item:hover .replace-btn {
  display: flex;
}

.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: #f5f7fa;
}

.pagination-container {
  text-align: center;
  margin-top: 20px;
}
</style>
